﻿using FRMS.BUS.ServerPlatform;
using FRMS.DAL;
using FRMS.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace FRMS.BUS
{
    public class DataAnalysisBUS
    {
        FRMSServer fxserver;

        public DataAnalysisBUS()
        {
            fxserver = (FRMSServer)ServicesLocator.Instance.GetService(typeof(FRMSServer));
        }
        public bool SendToDevice(string DeviceIP, string uuid, out string returncmd)
        {
            try
            {
                returncmd = "";
                DeviceDAL da = new DeviceDAL();
                DeviceInfo dev = da.QueryDevByHK(DeviceIP);
                VoucherDAL voucherDAL = new VoucherDAL();
                string authorized_floor = voucherDAL.QueryAuthorizedFloor(DeviceIP, uuid);
                List<int> floor_list = ConvertFloor(dev.FloorInfo, authorized_floor);
                CmdInfo cmdInfo = new CmdInfo();
                string cmd = string.Empty;
                if (floor_list.Count == 1)
                {
                    cmd = Floor(621, 5, floor_list);
                    cmdInfo.Address = 621;
                }
                else
                {
                    cmd = Floor(611, 5, floor_list);
                    cmdInfo.Address = 611;
                }
                returncmd = cmd;
                cmdInfo.Cmd = cmd;
                cmdInfo.DataLen = 5;
                cmdInfo.DevNo = 1;

                List<CmdInfo> list = new List<CmdInfo>();
                list.Add(cmdInfo);
                CmdMessage message = new CmdMessage();
                message.Command = "ISSUE_COMMAND";
                message.Data = list;
                string msg = fxserver.StringToHex(JsonConvert.SerializeObject(message));
                int datanum;
                msg = ProcessSendMsg(msg, out datanum);
                byte[] buffer = HexStringToByteArray(msg);
                string result = fxserver.SendMsgToDev(buffer, dev.DeviceNO);
                return true;
            }
            catch
            {
                returncmd = "send fail";
                return false;
            }
        }

        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

        public string ProcessSendMsg(string data, out int datanum)
        {
            int packnum = fxserver.GetPackNum();
            datanum = packnum;
            string datapack = IntToHex(packnum).PadLeft(8, '0');
            string datazs = datapack.Substring(0, 2) + " " + datapack.Substring(2, 2) + " " + datapack.Substring(4, 2) + " " + datapack.Substring(6, 2);
            string strCmd = data;
            int num = data.Split(' ').Length;
            string datalength = fxserver.IntToHex(num).PadLeft(8, '0').ToUpper();
            string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
            string crc = fxserver.CRCCalc(strCmd);
            strCmd = "48 44 58 4D " + fxserver.StringToHex("00000000000000000000") + " " + fxserver.StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;

            return strCmd;
        }

        public string IntToHex(int num)
        {
            string result = "";
            result = Convert.ToString(num, 16).ToUpper();
            return result;
        }

        public List<int> ConvertFloor(string floorinfo, string authorizedfloor)
        {
            List<int> list = new List<int>();
            List<string> strs = authorizedfloor.Trim().Split(',').ToList();
            List<string> str2 = floorinfo.Trim().Split(',').ToList();
            foreach (var item in strs)
            {
                if (str2.Contains(item))
                {
                    int idx = str2.IndexOf(item) + 1;
                    list.Add(idx);
                }
            }
            return list;
        }

        public string Floor(int add, int count, List<int> floor)
        {
            try
            {
                string strcmd = string.Empty;
                string strbyte = string.Empty;
                string strbit = string.Empty;
                for (int i = 1; i < 81; i++)
                {
                    var res1 = floor.Any(e => e == i);
                    if (!res1)
                    {
                        strbit = strbit + "0";
                    }
                    else
                    {
                        strbit = strbit + "1";
                    }
                }
                strbit = Reverse(strbit);

                strcmd = Convert.ToInt32(strbit.Substring(64, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(72, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                       Convert.ToInt32(strbit.Substring(48, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(56, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(32, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(40, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(16, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(24, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(0, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(8, 8), 2).ToString("X").PadLeft(2, '0');

                string addhex = (add - 1).ToString("X").PadLeft(4, '0');
                string numhex = count.ToString("X").PadLeft(4, '0');
                string bytecount = (2 * count).ToString("X").PadLeft(2, '0');
                strcmd = "01 10 " + addhex.Substring(0, 2) + " " + addhex.Substring(2, 2) + " " + numhex.Substring(0, 2) + " " + numhex.Substring(2, 2) + " " + bytecount + " " + strcmd;
                byte[] data = ToBytesSendDate(strcmd);
                byte[] crc = Crc18(data);
                strcmd += " " + crc[1].ToString("X").PadLeft(2, '0') + " " + crc[0].ToString("X").PadLeft(2, '0');

                return strcmd;
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public static string Reverse(string str)
        {
            char[] arr = str.ToCharArray();
            Array.Reverse(arr);
            return new string(arr);
        }

        #region CRC校验
        public byte[] Crc18(byte[] buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }
        #endregion

        public byte[] ToBytesSendDate(string str)
        {
            List<byte> result = new List<byte>();
            if (str.Contains(" "))
            {
                string[] strs = str.Trim().Split(' ');
                foreach (string s in strs)
                {
                    result.Add(Convert.ToByte(s.Trim(), 16));
                }
            }
            else
            {
                result.Add(Convert.ToByte(str, 16));
            }
            return result.ToArray();
        }


    }
}
